package cn.mw.cmdb.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.mw.cmdb.entity.AlgorithmInfo;
import cn.mw.cmdb.entity.InstanceMetricInfo;
import cn.mw.cmdb.enums.*;
import cn.mw.cmdb.exception.InputRequireException;
import cn.mw.cmdb.param.AlgorithmIdsParam;
import cn.mw.cmdb.param.AlgorithmSearchParam;
import cn.mw.cmdb.service.ServiceAction;
import cn.mw.cmdb.service.impl.AlgorithmInfoServiceImpl;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceMetricServiceImpl;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.exception.BusinessException;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.common.BaseApiService;
import cn.mw.microMonitorCommon.api.common.ResponseBase;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.operatorlog.client.MwLogClientSimple;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static cn.mw.cmdb.enums.PageDescEnum.Algorithm;

@Slf4j
@Tag(name = "算法管理")
@RestController
@RequestMapping("/algorithm")
public class AlgorithmConfigController extends BaseApiService {

    private final CmdbServiceManage cmdbServiceManage;

    private final ViewManager viewManager;

    @Autowired
    private MwLogClientSimple logClientSimple;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    public AlgorithmConfigController(CmdbServiceManage cmdbServiceManage, ViewManager viewManager) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.viewManager = viewManager;
    }

    /**
     * 算法生成
     */
    @Operation(summary = "算法生成")
    @PostMapping("/genAlgorithm")
    public ResponseBase<String> algorithm(@Validated @RequestBody AlgorithmInfo param) {
        AlgorithmInfoServiceImpl algorithmConfigService = (AlgorithmInfoServiceImpl) cmdbServiceManage.getModelService(AlgorithmInfoServiceImpl.ID);
        String ret = algorithmConfigService.algorithm(param);
        return this.setResultSuccess(ret);
    }

    @Operation(summary = "获取算法管理常量")
    @PostMapping("/getAlgorithmEnum")
    public ResponseBase<JSONObject> getAlgorithmEnum() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.putAll(BusynessStatisticalEnum.getAll());
        jsonObject.putAll(AlgorithmAvailableEnum.getAll());
        jsonObject.putAll(BusynessSystemUtilizationEnum.getAll());
        jsonObject.putAll(DateUnitEnum.getAll());
        jsonObject.putAll(HealthinessAlertEnum.getAll());
        jsonObject.putAll(AlgorithmEnum.getAll());
        return this.setResultSuccess(jsonObject);
    }

    @Operation(summary = "新增算法")
    @PostMapping("/add")
    public ResponseBase<Void> algorithmAdd(@Validated @RequestBody AlgorithmInfo param) throws Exception {
        String algorithmName = param.getAlgorithmName();
        if (StrUtil.isBlank(algorithmName)) {
            throw new InputRequireException(new Object[]{algorithmName});
        }
        if (algorithmName.length() > 30) {
            throw new BusinessException("business-name-over_length");
        }
        cmdbServiceManage.service(param, ServiceAction.add);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + Algorithm.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + param.getAlgorithmName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return this.setResultSuccess();
    }

    @Operation(summary = "更新算法")
    @PostMapping("/update")
    public ResponseBase<Void> algorithmUpdate(@Validated @RequestBody AlgorithmInfo param) throws Exception {
        String algorithmName = param.getAlgorithmName();
        if (StrUtil.isBlank(algorithmName)) {
            throw new InputRequireException(new Object[]{algorithmName});
        }
        if (algorithmName.length() > 30) {
            throw new BusinessException("business-name-over_length");
        }
        cmdbServiceManage.service(param, ServiceAction.update);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname() + Algorithm.getDesc(),
                        OperatorTypeDescEnum.update.getCname() + param.getAlgorithmName(), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return this.setResultSuccess();
    }
    @Operation(summary = "删除算法")
    @PostMapping("/delete")
    public ResponseBase<Void> algorithmDelete(@RequestBody AlgorithmIdsParam param) throws Exception {
        AlgorithmInfoServiceImpl modelService = (AlgorithmInfoServiceImpl) cmdbServiceManage.getModelService(AlgorithmInfoServiceImpl.ID);
        List<AlgorithmInfo> algorithmInfos = Optional.ofNullable(modelService.doSelectListByIds(param.getIds())).orElse(new ArrayList<>());
        List<String> list = algorithmInfos.stream().map(AlgorithmInfo::getAlgorithmName).toList();

        cmdbServiceManage.service(param, ServiceAction.batchRemove);

        String nickName = SecurityUtils.getUser().getNickName();
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname() + Algorithm.getDesc(),
                        OperatorTypeDescEnum.remove.getCname() + String.join(",", list), Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return this.setResultSuccess();
    }

    @Operation(summary = "算法列表")
    @PostMapping("/list")
    public ResponseBase algorithmList(@RequestBody AlgorithmSearchParam param) throws Exception {
        List list = (List) cmdbServiceManage.service(param, ServiceAction.list);
        Object ret = viewManager.getListViewObject(list, AlgorithmInfo.class, param, null);
        return this.setResultSuccess(ret);
    }

    @Operation(summary = "根据资产实例ID获取算法计算的信息")
    @PostMapping("/getAlgorithmByInstanceId")
    public ResponseBase getAlgorithmByInstanceId(String instanceId) throws Exception {
        InstanceMetricServiceImpl instanceMetricService = (InstanceMetricServiceImpl) cmdbServiceManage.getModelService(InstanceMetricServiceImpl.ID);
        InstanceMetricInfo info = instanceMetricService.getAlgorithmByInstanceId(instanceId);
        return setResultSuccess(info);
    }
}
